package com.njtoyo.taxi.admin.service.business.geo.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.njtoyo.taxi.admin.cache.PrimaryCachePutter;
import com.njtoyo.taxi.admin.handler.FilterHandler;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.logic.geo.CantonAreaLogic;
import com.njtoyo.taxi.admin.mapper.master.entity.GeoCanton;
import com.njtoyo.taxi.admin.mapper.master.entity.GeoCantonArea;
import com.njtoyo.taxi.admin.mapper.master.mapper.GeoCantonAreaMapper;
import com.njtoyo.taxi.admin.mapper.master.mapper.GeoCantonMapper;
import com.njtoyo.taxi.admin.rest.presenter.business.geo.AllListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.geo.RegionListPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.area.CantonQueryWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.canton.CantonCreateWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.canton.CantonUpdateWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.canton.RegionCreateWrapper;
import com.njtoyo.taxi.admin.service.business.geo.CantonService;
import com.njtoyo.taxi.admin.service.business.geo.GeoCustomerRegionService;
import com.njtoyo.taxi.admin.service.business.geo.GeoDriverRegionService;
import com.taxi.entity.common.RestResult;
import com.njtoyo.taxi.entity.backend.AdminUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
@DS(Const.PRIMARY_DS)
public class CantonServiceImpl implements CantonService {

    @Autowired
    private GeoCantonMapper geoCantonMapper;

    @Autowired
    private GeoCantonAreaMapper geoCantonAreaMapper;

    @Autowired
    private GeoCustomerRegionService geoCustomerRegionService;

    @Autowired
    private GeoDriverRegionService geoDriverRegionService;

    @Autowired
    private CantonAreaLogic cantonAreaLogic;
    @Autowired
    private PrimaryCachePutter primaryCachePutter;

    @Override
    public RestResult getAll(AdminUser adminUser) {
        FilterHandler filterHandler = new FilterHandler(adminUser, null, null);
        QueryWrapper<GeoCanton> wrapper = new QueryWrapper<>();

        switch (filterHandler.getFilterType()) {
            case canton:
            case company:
                wrapper.in("id", filterHandler.getCantonIds());
                break;
        }
        wrapper.select("id, name, pinyin");
        List<GeoCanton> res = geoCantonMapper.selectList(wrapper);

        return RestResult.success(res);
    }

    @Override
    @Transactional
    public RestResult create(CantonCreateWrapper wrapper) {
        // 校验是否已经存在area_id
        Boolean checkAreaIdsExist = this.checkAreaIdsExist(null, wrapper.getAreaIds());
        if (checkAreaIdsExist) {
            return RestResult.failed("地区已被行政区引用，请检查所选择的地区");
        }

        // geo_canton
        GeoCanton canton = new GeoCanton();
        canton.setName(wrapper.getName());
        canton.setPinyin(wrapper.getPinyin());
        canton.setIsHot(wrapper.getIsHot());
        geoCantonMapper.insert(canton);

        Long cantonId = canton.getId();

        // geo_canton_area
        cantonAreaLogic.createInsert(cantonId, wrapper.getAreaIds());

        // geo_customer_region
        if (wrapper.getOpenCustomerRegion()) {
            RegionCreateWrapper customerCreateWrapper = new RegionCreateWrapper();
            customerCreateWrapper.setName(wrapper.getName() + "运营区");
            customerCreateWrapper.setAreaIds(wrapper.getAreaIds());
            geoCustomerRegionService.create(customerCreateWrapper);
        }

        // geo_driver_region
        if (wrapper.getOpenDriverRegion()) {
            RegionCreateWrapper driverCreateWrapper = new RegionCreateWrapper();
            driverCreateWrapper.setName(wrapper.getName() + "运营区");
            driverCreateWrapper.setAreaIds(wrapper.getAreaIds());
            geoDriverRegionService.create(driverCreateWrapper);
        }
        //清除缓存
        primaryCachePutter.deleteAllCanton();
        return RestResult.success();
    }

    @Override
    public RestResult<IPage<RegionListPresenter>> getList(CantonQueryWrapper wrapper) {
        IPage<RegionListPresenter> res = geoCantonMapper.getListByPage(wrapper);
        List<Long> cantonIds = res.getRecords().stream().map(RegionListPresenter::getId).collect(Collectors.toList());
        if (cantonIds.size() > 0) {
            List<AllListPresenter> areaList = geoCantonMapper.getListByCantonIds(cantonIds);
            for (RegionListPresenter canton : res.getRecords()) {
                List<AllListPresenter> itemAreaList = new ArrayList<>();
                for (AllListPresenter area : areaList) {
                    if (canton.getId().equals(area.getRegionId())) {
                        itemAreaList.add(area);
                    }
                }
                canton.setAreaList(itemAreaList);
            }
        }

        return RestResult.success(res);
    }

    @Override
    @Transactional
    public RestResult<Boolean> update(Long id, CantonUpdateWrapper wrapper) {
        // 校验是否已经存在area_id
        Boolean checkAreaIdsExist = this.checkAreaIdsExist(id, wrapper.getAreaIds());
        if (checkAreaIdsExist) {
            return RestResult.failed("地区已被行政区引用，请检查所选择的地区");
        }

        // geo_canton
        new LambdaUpdateChainWrapper<>(geoCantonMapper)
                .eq(GeoCanton::getId, id)
                .set(Objects.nonNull(wrapper.getName()), GeoCanton::getName, wrapper.getName())
                .set(Objects.nonNull(wrapper.getPinyin()), GeoCanton::getPinyin, wrapper.getPinyin())
                .set(Objects.nonNull(wrapper.getIsHot()), GeoCanton::getIsHot, wrapper.getIsHot())
                .update();

        // geo_canton_area
        if (Objects.nonNull(wrapper.getAreaIds()) && !wrapper.getAreaIds().isEmpty()) {
            // 删除原有areaIds
            QueryWrapper<GeoCantonArea> deleteArea = new QueryWrapper<>();
            deleteArea.eq("canton_id", id);
            geoCantonAreaMapper.delete(deleteArea);

            // 写入新的areaIds
            cantonAreaLogic.createInsert(id, wrapper.getAreaIds());
        }

        //清除缓存
        primaryCachePutter.deleteAllCanton();

        return RestResult.success();
    }

    @Override
    public RestResult listAll() {
        List<GeoCanton> geoCantons = geoCantonMapper.selectList(null);
        return RestResult.success(geoCantons);
    }

    @Override
    public GeoCanton getInfoById(Long id) {
        QueryWrapper<GeoCanton> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        return geoCantonMapper.selectOne(wrapper);
    }

    // 校验是否已经存在area_id
    private Boolean checkAreaIdsExist(Long cantonId, List<Long> areaIds) {
        if (Objects.isNull(areaIds) || areaIds.isEmpty()) {
            return false;
        }

        Integer areaCheckCount = new LambdaQueryChainWrapper<>(geoCantonAreaMapper)
                .in(GeoCantonArea::getAreaId, areaIds)
                .ne(Objects.nonNull(cantonId), GeoCantonArea::getCantonId, cantonId)
                .count();

        return areaCheckCount > 0;
    }

}
